From: kaf24@firebug.cl.cam.ac.uk Date: Wed, 13 Sep 2006 13:05:33 +0000 (+0100) Subject: Add new operation XENOPROF_get_buffer in xenoprof hypercall. Also X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15658^2~53^2~10 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=d4b644873dd4dfe06aff9dd1c9e6cde92f99d006;p=xen.git Add new operation XENOPROF_get_buffer in xenoprof hypercall. Also remove buffer related arguments from XENOPROF_init operation. This is the first step to allow dynamic mapping/unmapping of xenoprof buffers to enable profiling a domain in passive mode and then switch to active mode (or vice-versa). Currently a domain can only be profiled in a single mode. Also passive domains cannot have oprofile builtin the kernel or passive profiling will fail. Signed-off-by: Jose Renato Santos --- diff --git a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c index 689a8e335f..ed648c72cd 100644 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c @@ -32,6 +32,8 @@ #include <../../../drivers/oprofile/cpu_buffer.h> #include <../../../drivers/oprofile/event_buffer.h> +#define MAX_XENOPROF_SAMPLES 16 + static int xenoprof_start(void); static void xenoprof_stop(void); @@ -43,7 +45,7 @@ static int active_defined; /* sample buffers shared with Xen */ xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; /* Shared buffer area */ -char * shared_buffer; +char * shared_buffer = NULL; /* Number of buffers in shared area (one per VCPU) */ int nbuf; /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ @@ -233,13 +235,57 @@ static int bind_virq(void) } +static int map_xenoprof_buffer(int max_samples) +{ + struct xenoprof_get_buffer get_buffer; + struct xenoprof_buf *buf; + int npages, ret, i; + struct vm_struct *area; + + if ( shared_buffer ) + return 0; + + get_buffer.max_samples = max_samples; + + if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) ) + return ret; + + nbuf = get_buffer.nbuf; + npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1; + + area = alloc_vm_area(npages * PAGE_SIZE); + if (area == NULL) + return -ENOMEM; + + if ( (ret = direct_kernel_remap_pfn_range( + (unsigned long)area->addr, + get_buffer.buf_maddr >> PAGE_SHIFT, + npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) { + vunmap(area->addr); + return ret; + } + + shared_buffer = area->addr; + for (i=0; i< nbuf; i++) { + buf = (struct xenoprof_buf*) + &shared_buffer[i * get_buffer.bufsize]; + BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); + xenoprof_buf[buf->vcpu_id] = buf; + } + + return 0; +} + + static int xenoprof_setup(void) { int ret; int i; - ret = bind_virq(); - if (ret) + if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) ) + return ret; + + if ( (ret = bind_virq()) ) return ret; if (is_primary) { @@ -482,51 +528,19 @@ static int using_xenoprof; int __init oprofile_arch_init(struct oprofile_operations * ops) { struct xenoprof_init init; - struct xenoprof_buf *buf; - int npages, ret, i; - struct vm_struct *area; + int ret, i; - init.max_samples = 16; ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init); if (!ret) { - pgprot_t prot = __pgprot(_KERNPG_TABLE); - num_events = init.num_events; is_primary = init.is_primary; - nbuf = init.nbuf; /* just in case - make sure we do not overflow event list - (i.e. counter_config list) */ + (i.e. counter_config list) */ if (num_events > OP_MAX_COUNTER) num_events = OP_MAX_COUNTER; - npages = (init.bufsize * nbuf - 1) / PAGE_SIZE + 1; - - area = alloc_vm_area(npages * PAGE_SIZE); - if (area == NULL) { - ret = -ENOMEM; - goto out; - } - - ret = direct_kernel_remap_pfn_range( - (unsigned long)area->addr, - init.buf_maddr >> PAGE_SHIFT, - npages * PAGE_SIZE, prot, DOMID_SELF); - if (ret) { - vunmap(area->addr); - goto out; - } - - shared_buffer = area->addr; - - for (i=0; i< nbuf; i++) { - buf = (struct xenoprof_buf*) - &shared_buffer[i * init.bufsize]; - BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); - xenoprof_buf[buf->vcpu_id] = buf; - } - /* cpu_type is detected by Xen */ cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0; strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1); @@ -541,7 +555,6 @@ int __init oprofile_arch_init(struct oprofile_operations * ops) active_defined = 0; } - out: printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, " "is_primary %d\n", ret, num_events, is_primary); return ret; diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c index cc0dcc7816..479d9c5060 100644 --- a/xen/arch/x86/oprofile/xenoprof.c +++ b/xen/arch/x86/oprofile/xenoprof.c @@ -437,54 +437,59 @@ void xenoprof_log_event( int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg) { struct xenoprof_init xenoprof_init; - int is_primary, num_events; - struct domain *d = current->domain; int ret; if ( copy_from_guest(&xenoprof_init, arg, 1) ) return -EFAULT; - ret = nmi_init(&num_events, - &is_primary, - xenoprof_init.cpu_type); - if ( ret < 0 ) - goto err; + if ( (ret = nmi_init(&xenoprof_init.num_events, + &xenoprof_init.is_primary, + xenoprof_init.cpu_type)) ) + return ret; - if ( is_primary ) + if ( copy_to_guest(arg, &xenoprof_init, 1) ) + return -EFAULT; + + if ( xenoprof_init.is_primary ) primary_profiler = current->domain; + return 0; +} + +int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg) +{ + struct xenoprof_get_buffer xenoprof_get_buffer; + struct domain *d = current->domain; + int ret; + + if ( copy_from_guest(&xenoprof_get_buffer, arg, 1) ) + return -EFAULT; + /* - * We allocate xenoprof struct and buffers only at first time xenoprof_init + * We allocate xenoprof struct and buffers only at first time xenoprof_get_buffer * is called. Memory is then kept until domain is destroyed. */ if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples, 0)) < 0) ) - goto err; + ((ret = alloc_xenoprof_struct(d, xenoprof_get_buffer.max_samples, 0)) < 0) ) + return ret; xenoprof_reset_buf(d); d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; d->xenoprof->domain_ready = 0; - d->xenoprof->is_primary = is_primary; - - xenoprof_init.is_primary = is_primary; - xenoprof_init.num_events = num_events; - xenoprof_init.nbuf = d->xenoprof->nbuf; - xenoprof_init.bufsize = d->xenoprof->bufsize; - xenoprof_init.buf_maddr = __pa(d->xenoprof->rawbuf); - - if ( copy_to_guest(arg, &xenoprof_init, 1) ) - { - ret = -EFAULT; - goto err; - } + if ( primary_profiler == current->domain ) + d->xenoprof->is_primary = 1; + else + d->xenoprof->is_primary = 0; + + xenoprof_get_buffer.nbuf = d->xenoprof->nbuf; + xenoprof_get_buffer.bufsize = d->xenoprof->bufsize; + xenoprof_get_buffer.buf_maddr = __pa(d->xenoprof->rawbuf); - return ret; + if ( copy_to_guest(arg, &xenoprof_get_buffer, 1) ) + return -EFAULT; - err: - if ( primary_profiler == current->domain ) - primary_profiler = NULL; - return ret; + return 0; } #define PRIV_OP(op) ( (op == XENOPROF_set_active) \ @@ -512,6 +517,10 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg) ret = xenoprof_op_init(arg); break; + case XENOPROF_get_buffer: + ret = xenoprof_op_get_buffer(arg); + break; + case XENOPROF_reset_active_list: { reset_active_list(); diff --git a/xen/include/public/xenoprof.h b/xen/include/public/xenoprof.h index a0bdd56ac3..a788c36f2b 100644 --- a/xen/include/public/xenoprof.h +++ b/xen/include/public/xenoprof.h @@ -28,6 +28,8 @@ #define XENOPROF_disable_virq 11 #define XENOPROF_release_counters 12 #define XENOPROF_shutdown 13 +#define XENOPROF_get_buffer 14 +#define XENOPROF_last_op 14 #define MAX_OPROF_EVENTS 32 #define MAX_OPROF_DOMAINS 25 @@ -56,17 +58,22 @@ typedef struct xenoprof_buf xenoprof_buf_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t); struct xenoprof_init { - int32_t max_samples; int32_t num_events; int32_t is_primary; - int32_t nbuf; - int32_t bufsize; - uint64_t buf_maddr; char cpu_type[XENOPROF_CPU_TYPE_SIZE]; }; typedef struct xenoprof_init xenoprof_init_t; DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t); +struct xenoprof_get_buffer { + int32_t max_samples; + int32_t nbuf; + int32_t bufsize; + uint64_t buf_maddr; +}; +typedef struct xenoprof_get_buffer xenoprof_get_buffer_t; +DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t); + struct xenoprof_counter { uint32_t ind; uint64_t count;